using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Globalization;
using Apache.NMS;

namespace SimpleServiceBus.Endpoints.ActiveMQ.Configuration {

    public class ActiveMQConsumerPoolConfigurator {

        //-----< Fields >-----
        //----------------------------------------------------------------------------------        
        private Int32 fWorkerCount = 1;
        private Dictionary<String, ActiveMQQueueConfiguration> fQueues = new Dictionary<String, ActiveMQQueueConfiguration>();
        private Dictionary<String, ActiveMQTopicConfiguration> fTopics = new Dictionary<String, ActiveMQTopicConfiguration>();


        //-----< Constructors >-----
        //----------------------------------------------------------------------------------        

        public ActiveMQConsumerPoolConfigurator() {
            this.AcknowledgementMode = AcknowledgementMode.Transactional;
        }

        //-----< Public and protected properties >-----
        //----------------------------------------------------------------------------------        

        public AcknowledgementMode AcknowledgementMode {
            get;
            set;
        }

        public IEnumerable<ActiveMQQueueConfiguration> Queues {
            get { return fQueues.Values; }
        }

        public IEnumerable<ActiveMQTopicConfiguration> Topics {
            get { return fTopics.Values; }
        }

        public Int32 WorkerCount {
            get { return fWorkerCount; }
            set {
                if(fWorkerCount != value) {
                    if(value < 1)
                        throw new ArgumentOutOfRangeException("value", String.Format(CultureInfo.InvariantCulture, "value must be >= 1"));
                    fWorkerCount = value;
                }
            }
        }


        //-----< Public and protected methods >-----
        //----------------------------------------------------------------------------------        

        public ActiveMQQueueConfiguration ConsumeQueue(String queueName) {
            return ConsumeQueue(queueName, null, false);
        }

        public ActiveMQQueueConfiguration ConsumeQueue(String queueName, String selector) {
            return ConsumeQueue(queueName, selector, false);
        }

        public ActiveMQQueueConfiguration ConsumeQueue(String queueName, Boolean isExclusive) {
            return ConsumeQueue(queueName, null, isExclusive);
        }

        public ActiveMQQueueConfiguration ConsumeQueue(String queueName, String selector, Boolean isExclusive) {
            if(queueName == null)
                throw new ArgumentNullException("queueName");
            ActiveMQQueueConfiguration _queue;
            if(!fQueues.TryGetValue(queueName, out _queue)) {
                _queue = new ActiveMQQueueConfiguration();
                _queue.Name = queueName;
                fQueues[queueName] = _queue;
            }
            _queue.Selector = selector;
            _queue.IsExclusive = isExclusive;
            return _queue;
        }
        
        public ActiveMQTopicConfiguration Subscribe(String topic) {
            return Subscribe(topic, null, false, null);
        }

        public ActiveMQTopicConfiguration Subscribe(String topic, Boolean noLocal) {
            return Subscribe(topic, null, noLocal, null);
        }

        public ActiveMQTopicConfiguration Subscribe(String topic, String selector) {
            return Subscribe(topic, selector, false, null);
        }

        public ActiveMQTopicConfiguration Subscribe(String topic, String selector, Boolean noLocal) {
            return Subscribe(topic, selector, noLocal, null);
        }

        public ActiveMQTopicConfiguration Subscribe(String topic, String selector, Boolean noLocal, String durableName) {
            ActiveMQTopicConfiguration _topic;
            if(!fTopics.TryGetValue(topic, out _topic)) {
                _topic = new ActiveMQTopicConfiguration();
                _topic.Name = topic;
                fTopics[topic] = _topic;
            }
            _topic.Selector = selector;
            _topic.NoLocal = noLocal;
            _topic.DurableSubscriptionName = durableName;
            return _topic;
        }

        public ActiveMQTopicConfiguration Subscribe(Type topicType) {
            return Subscribe(topicType, null, false, null);
        }

        public ActiveMQTopicConfiguration Subscribe(Type topicType, Boolean noLocal) {
            return Subscribe(topicType, null, noLocal, null);
        }

        public ActiveMQTopicConfiguration Subscribe(Type topicType, String selector) {
            return Subscribe(topicType, selector, false, null);
        }

        public ActiveMQTopicConfiguration Subscribe(Type topicType, String selector, Boolean noLocal) {
            return Subscribe(topicType, selector, noLocal, null);
        }

        public ActiveMQTopicConfiguration Subscribe(Type topicType, String selector, Boolean noLocal, String durableName) {
            return Subscribe(CreateTopicFrom(topicType), selector, noLocal, durableName);
        }


        protected virtual String CreateTopicFrom(Type topicType) {
            var _resolver = new DefaultDestinationResolver();
            return _resolver.Resolve(topicType).ToString();
        }

        //-----< Events >-----
        //----------------------------------------------------------------------------------        


        //-----< Internal members >-----
        //----------------------------------------------------------------------------------        


        //-----< Private members >-----
        //----------------------------------------------------------------------------------        


        //-----< All nested types >-----
        //----------------------------------------------------------------------------------        


        //-----< All explicit interface implementations >-----
        //----------------------------------------------------------------------------------        


    }
}

